﻿using NJsonSchema.CodeGeneration;
using NJsonSchema.CodeGeneration.CSharp;
using NSwag;
using NSwag.CodeGeneration.CSharp;
using NSwag.CodeGeneration.Models;
using System.Collections.Generic;
using NSwag.CodeGeneration;
using System.Linq;
using System;
using NSwag.CodeGeneration.CSharp.Models;
using NJsonSchema;
using Xunit;
using Coldairarrow.Business.Base_Manage;
using Coldairarrow.Entity.Base_Manage;
using Coldairarrow.Util;

namespace Coldairarrow.Api
{
    public class MultiCSharpControllerGenerator : MultiCSharpGeneratorBase
    {
        private readonly OpenApiDocument _document;
        /// <summary>Initializes a new instance of the <see cref="CSharpControllerGenerator" /> class.</summary>
        /// <param name="document">The Swagger document.</param>
        /// <param name="settings">The settings.</param>
        /// <exception cref="ArgumentNullException"><paramref name="document" /> is <see langword="null" />.</exception>
        public MultiCSharpControllerGenerator(OpenApiDocument document, CSharpControllerGeneratorSettings settings)
            : this(document, settings, CreateResolverWithExceptionSchema(settings.CSharpGeneratorSettings, document))
        {
        }

        /// <summary>Initializes a new instance of the <see cref="CSharpControllerGenerator" /> class.</summary>
        /// <param name="document">The Swagger document.</param>
        /// <param name="settings">The settings.</param>
        /// <param name="resolver">The resolver.</param>
        /// <exception cref="ArgumentNullException"><paramref name="document" /> is <see langword="null" />.</exception>
        public MultiCSharpControllerGenerator(OpenApiDocument document, CSharpControllerGeneratorSettings settings, CSharpTypeResolver resolver)
            : base(document, settings, resolver)
        {
            _document = document ?? throw new ArgumentNullException(nameof(document));
            Settings = settings ?? throw new ArgumentNullException(nameof(settings));
        }
     

        /// <summary>Gets or sets the generator settings.</summary>
        public CSharpControllerGeneratorSettings Settings { get; set; }

        /// <summary>Gets the base settings.</summary>
        public override ClientGeneratorBaseSettings BaseSettings => Settings;

        /// <summary>
        /// 获取请求和返回值实体类型代码集合
        /// </summary>
        /// <returns></returns>
        public new IEnumerable<CodeArtifact> GenerateDtoTypes()
        {
            return base.GenerateDtoTypes();
           // return GenerateDtoTypes();
        }

        /// <summary>
        /// 获取客户端代码集合
        /// </summary>
        /// <returns></returns>
        public IEnumerable<CodeArtifact> GenerateAllClientTypes_(string controllerName, string controllerClassName, IEnumerable<MultiCSharpOperationModel> operations)
        {
            return GenerateClientTypes(controllerName, controllerClassName, operations);
            
        }
        /// <summary>
        /// 获取客户端代码集合
        /// </summary>
        /// <returns></returns>
        public new IEnumerable<CodeArtifact> GenerateAllClientTypes222()
        {
           //return base.GenerateAllClientTypes();
           return GenerateAllClientTypes000();
        }
    
        public new IEnumerable<CodeArtifact> GenerateAllClientTypes000()
        {
            List<CodeArtifact> list = base.GenerateAllClientTypes().ToList();
            var template = @"D:\项目\框架\Colder.Admin.AntdVue6.0\src\Coldairarrow.Api\BuildCodeTemplate\openapi\Controller.liquid";
            list.Add(new CodeArtifact("Controller", CodeArtifactType.Class, CodeArtifactLanguage.CSharp, CodeArtifactCategory.Utility, template));
            //List<CodeArtifact> list = Base.GenerateAllClientTypes().ToList();
            //if (Settings.ControllerTarget == CSharpControllerTarget.AspNet && _document.Operations.Count((OpenApiOperationDescription operation) => operation.Operation.ActualParameters.Any((OpenApiParameter p) => p.Kind == OpenApiParameterKind.Header)) > 0)
            //{
            //    //ITemplate template = Settings.CodeGeneratorSettings.TemplateFactory.CreateTemplate("CSharp", "Controller.AspNet.FromHeaderAttribute", new object());
            //    template = @"D:\项目\框架\Colder.Admin.AntdVue6.0\src\Coldairarrow.Api\BuildCodeTemplate\openapi\Controller.AspNet.FromHeaderAttribute.liquid";
            //    list.Add(new CodeArtifact("FromHeaderAttribute", CodeArtifactType.Class, CodeArtifactLanguage.CSharp, CodeArtifactCategory.Utility, template));
            //    //template = Settings.CodeGeneratorSettings.TemplateFactory.CreateTemplate("CSharp", "Controller.AspNet.FromHeaderBinding", new object());
            //    template = @"D:\项目\框架\Colder.Admin.AntdVue6.0\src\Coldairarrow.Api\BuildCodeTemplate\openapi\Controller.AspNet.FromHeaderBinding.liquid";
            //    list.Add(new CodeArtifact("FromHeaderBinding", CodeArtifactType.Class, CodeArtifactLanguage.CSharp, CodeArtifactCategory.Utility, template));
            //}

            return list;
        }
        /// <summary>
        /// 获取客户端代码集合
        /// </summary>
        /// <returns></returns>

        public new IEnumerable<CodeArtifact> GenerateAllClientTypes2()
        {
            var artifacts = base.GenerateAllClientTypes().ToList();

            //var template = Settings.CodeGeneratorSettings.TemplateFactory.CreateTemplate("CSharp", "Controller.AspNet.FromHeaderAttribute", new object());
            var template = @"D:\项目\框架\Colder.Admin.AntdVue6.0\src\Coldairarrow.Api\BuildCodeTemplate\openapi\Controller.AspNet.FromHeaderAttribute.liquid";
            //var template = Settings.CodeGeneratorSettings.TemplateFactory.CreateTemplate(@"D:\项目\框架\Colder.Admin.AntdVue6.0\src\Coldairarrow.Api\BuildCodeTemplate\openapi", "Controller.AspNet.FromHeaderAttribute.liquid", new object());
            artifacts.Add(new CodeArtifact("FromHeaderAttribute", CodeArtifactType.Class, CodeArtifactLanguage.CSharp, CodeArtifactCategory.Utility, template));
            template = @"D:\项目\框架\Colder.Admin.AntdVue6.0\src\Coldairarrow.Api\BuildCodeTemplate\openapi\Controller.AspNet.FromHeaderBinding.liquid";
            //template = Settings.CodeGeneratorSettings.TemplateFactory.CreateTemplate(@"D:\项目\框架\Colder.Admin.AntdVue6.0\src\Coldairarrow.Api\BuildCodeTemplate\openapi", "Controller.AspNet.FromHeaderBinding.liquid", new object());
            artifacts.Add(new CodeArtifact("FromHeaderBinding", CodeArtifactType.Class, CodeArtifactLanguage.CSharp, CodeArtifactCategory.Utility, template));

            return artifacts;
        }

        /// <summary>Generates the client types.</summary>
        /// <returns>The code artifact collection.</returns>
        public override IEnumerable<CodeArtifact> GenerateAllClientTypes()
        {
            var artifacts = base.GenerateAllClientTypes().ToList();

            if (Settings.ControllerTarget == CSharpControllerTarget.AspNetCore &&
                _document.Operations.Count(operation => operation.Operation.ActualParameters.Any(p => p.Kind == OpenApiParameterKind.Header)) > 0)
            {
                var template = Settings.CodeGeneratorSettings.TemplateFactory.CreateTemplate("CSharp", "Controller.AspNet.FromHeaderAttribute", new object());
                artifacts.Add(new CodeArtifact("FromHeaderAttribute", CodeArtifactType.Class, CodeArtifactLanguage.CSharp, CodeArtifactCategory.Utility, template));

                template = Settings.CodeGeneratorSettings.TemplateFactory.CreateTemplate("CSharp", "Controller.AspNet.FromHeaderBinding", new object());
                artifacts.Add(new CodeArtifact("FromHeaderBinding", CodeArtifactType.Class, CodeArtifactLanguage.CSharp, CodeArtifactCategory.Utility, template));
            }

            return artifacts;
        }

        public List<Base_ApiList> GetApiMessage(IEnumerable<MultiCSharpOperationModel> operations, string search)
        {
            List<Base_ApiList> newlist = new List<Base_ApiList>();
            var list = GetOperations(_document);
            if (!search.IsNullOrEmpty())
            {
                list = list.Where(x => x.ControllerName.Contains(search)).ToList();
            }
            foreach (var p in list)
            {
                Base_ApiList model = new Base_ApiList();

                model.Id = p.Id;
                model.Path = p.Path;
                model.Summary = p.Summary;
                model.Method = p.HttpMethod;
                model.ControllerClassName = GetControllerClassName(p.ControllerName);
                model.ApiUrl = p.Path;
                model.Tags = p.ControllerName;
                model.CreateTime = DateTime.Now;
                newlist.Add(model);
            }
            return newlist;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="ControllerName"></param>
        /// <returns></returns>
        public string GetControllerClassName(string ControllerName)
        {
           return BaseSettings.GenerateControllerName(ControllerName);
        }

        public List<ControllerDTO> GetControllerNames(IEnumerable<MultiCSharpOperationModel> operations)
        {
            var clientTypes = new List<ControllerDTO>();
            var q = operations = GetOperations(_document);
            var controllerOperationsGroups = operations.GroupBy(o => o.ControllerName);
            foreach (var controllerOperations in controllerOperationsGroups)
            {
                var controllerName = controllerOperations.Key;
                var controllerClassName = BaseSettings.GenerateControllerName(controllerOperations.Key);
                //var clientType = GenerateClientTypes(controllerName, controllerClassName, controllerOperations.ToList());
                clientTypes.Add(new ControllerDTO { ControllerName =controllerName, ControllerClassName =controllerClassName });
            }
            return clientTypes;
        }

        public class ControllerDTO
        {
            public string ControllerName { get; set; }

            public string ControllerClassName { get; set; }
        }
        protected override MultiCSharpOperationModel MultiCSharpOperationModel(OpenApiOperation operation, ClientGeneratorBaseSettings settings)
        {
            return new MultiCSharpControllerOperationModel(operation, (CSharpControllerGeneratorSettings)settings, this, (CSharpTypeResolver)Resolver);
        }

       
        /// <summary>Generates the client class.</summary>
        /// <param name="controllerName">Name of the controller.</param>
        /// <param name="controllerClassName">Name of the controller class.</param>
        /// <param name="operations">The operations.</param>
        /// <returns>The code.</returns>
        protected override IEnumerable<CodeArtifact> GenerateClientTypes(string controllerName, string controllerClassName, IEnumerable<MultiCSharpOperationModel> operations)
        {
            operations = GetOperations(_document).Where(x=>x.ControllerName==controllerName);

            var model = new MultiCSharpControllerTemplateModel(controllerClassName, operations, _document, Settings);
            var template = Settings.CodeGeneratorSettings.TemplateFactory.CreateTemplate("CSharp", "Controller", model);
           
            yield return new CodeArtifact(model.Class, CodeArtifactType.Class, CodeArtifactLanguage.CSharp, CodeArtifactCategory.Client, template);
        }
    }
}
